	title   "Micro Lab - Mini Project - Battle Ship - Shai Givony"
; The program is "Battleship"

	list     p=18f452
	#include <p18f452.inc>


;Program Configuration Registers:
	__CONFIG    _CONFIG1H, _HS_OSC_1H		;For use with 4 MHz clock osc.
	__CONFIG    _CONFIG2H, _WDT_OFF_2H		;Watchdog Timer disabled.
	__CONFIG    _CONFIG2L, _BOR_OFF_2L & _PWRT_ON_2L
	__CONFIG    _CONFIG4L, _LVP_OFF_4L		;Low Voltage in-circutit ...

; Externs & Globals:
  	extern BIN2BCD, UASCI, HASCI, LASCI
  	extern USART_INIT, TXbyte, RXbyte, RX0byte, TXcrlf, TXstr_1, TMR0_init, R0Xfl
  	GLOBAL stan_table, ptr_pos

; Variables Declarations:
S_DATA      	UDATA
; - - - - - - - - - -
COUNTER 						res 1  
COUNTER_TMP						res 1
COUNTER_ROWS					res 1
COUNTER_COLS					res 1
COUNTER_ROWS_1					res 1
COUNTER_COLS_1					res 1

HOW_MANY_USER_SUBMARINES_LEFT	res 1
HOW_MANY_COMP_SUBMARINES_LEFT	res 1
SOMEONE_WINS					res 1

TMP								res 1
TMP1							res 1
TMP2							res 1
BYTES_TO_MOVE					res 1
GET_CELL						res 1

WHAT_TO_PUT						res 1
ROW								res 1
COL								res 1
ROW_TMP							res 1
COL_TMP							res 1
ROW_TMP1						res 1
COL_TMP1						res 1
UPPER_COMMON_ROW				res	1
LOWER_COMMON_ROW				res	1


ROW_DISTANCE					res 1
COL_DISTANCE					res 1

USER_TURN						res 1
COMP_TURN						res 1
USER_MODE						res	1
COMP_MODE						res	1
COMP_FOUND_SUB_TO_MOVE			res	1
USER_FOUND_SUB_TO_MOVE			res	1
COMP_MOVING_SUB_ROW				res	1	; This is a user's sub, that computer takes and moves it
COMP_MOVING_SUB_COL				res	1	; This is a user's sub, that computer takes and moves it
USER_MOVING_SUB_ROW				res	1	; This is a computer's sub, that user takes and moves it
USER_MOVING_SUB_COL				res	1	; This is a computer's sub, that user takes and moves it

VALIDATION						res 1

SUBMARINES_COMP_COUNTER			res 1
SUBMARINES_USER_COUNTER 		res 1

FEEDBACK						res 1
FEEDBACK_COMP					res 1
FEEDBACK_USER					res 1
USER_WAS_HIT_BEFORE				res 1
COMP_WAS_HIT_BEFORE				res 1

WHAT_TO_LOOK_FOR 				res 1
RANDOM							res 1

NEAR							res 1
COMP_LAST_GUESS_ROW				res 1
COMP_LAST_GUESS_COL				res 1
COMP_IN_MODE_NEAR				res 1
COMP_IN_MODE_NEAR_ROUND_SEARCH	res	1
EXCEEDED						res 1
RANDOM_TRIES					res 1


ptr_pos        					res 1           ; for USART


; - - - - - - - - - - -
STARTUP    CODE
	org	    00h
 	bra     Main

; - - - - - - - - - - -

PROG     CODE
;----------------------------
stan_table
;----------------------------
game_title						db	"\t\t          Battle Ship    \n\r\0"
user_starts						db	"\n\r   User will play first.\n\n\r\0"
comp_starts						db	"\n\r\tComputer will play first.\n\n\r\0"
request_from_user				db	"   User, please enter submarine location (Row 2 to 7, Column 0 to 7):\n\r\0"
row_request						db	"   Row   : \0"
column_request					db	"\tColumn: \0"
name_request					db	"   Name  : \0"
location_is_valid				db	"\n   OK.\n\r\0"
location_is_not_valid			db	"\n   Location is NOT valid, try again.\n\r\0"
help_comp_to_place_sub			db	"\n\r\tPlease hit a key to help computer place submarine\0"
guess_from_user					db	"   User, what's your guess?\n\r\0"
guess_from_comp					db	"   Computer guesses: \0"
feedback_hit					db	"\t# One Shot - One Kill!\0"
feedback_near					db	"\t# NEAR...\0"
feedback_miss					db	"\t# Not Even Close... Ha Ha Ha!\0"
trying_to_hit_a_hit_sub			db	"\n\r # Don't fool me! You're trying to hit the same submarine twice..\n\r\0"
computer_wins_msg				db	"\n\r\t\t********************************\n\r\t\t***  COMPUTER IS THE WINNER  ***\n\r\t\t********************************\n\r\0"
user_wins_msg					db	"\n\r\t\t****************************\n\r\t\t***  USER IS THE WINNER  ***\n\r\t\t****************************\n\r\0"
play_again?						db	"\n\r   Play Again (y/n)? \0"
good_bye_message				db	"\n            See ya'...\0"
reverse_one						db	"\b\0"
comp_will_place_only_4_subs		db	"\n\n\r\t   Computer will place only 4 submarines!\n\r\0"
user_will_place_only_4_subs		db	"\n\r\t   User will place only 4 submarines!\n\r\0"
user_found_sub_to_move			db	"\tUser is kidnapping submarine at \0"
comp_found_sub_to_move			db	"\tComputer is kidnapping submarine at \0"
user_is_moving_sub				db	"\tUser is moving kidnapped submarine one more step..\0"
comp_is_moving_sub				db	"\tComputer is moving kidnapped submarine one more step..\0"
newline							db	"\n\r\0"
user_is_wrong					db	"\n\r\tUser, you are wrong. You COULD place another submarine.\n\r\0"
do_you_want_to_place_last_sub	db	"\tDo you want to place last submarine? (y/n) \0"
;----------------------------


; Constants:
; ----------
initial_number_of_submarines	equ	.5

comp_sub			equ	b'00010000'
comp_hitted_sub		equ	b'00110000'
comp_guess			equ	b'01000000'
comp_guess_miss		equ	b'10000000'

user_sub			equ	b'00000001'
user_hitted_sub		equ	b'00000011'
user_guess			equ	b'00000100'
user_guess_miss		equ	b'00001000'

rows_number			equ	.8
cols_number			equ	.8

; booleans:
true				equ	.1
false				equ	.0

; feedbacks:
miss				equ	.0  ; means  Miss, completely
near				equ .1	; means  Miss, but 1 cell far from hit (may be in any direction)
hit					equ	.2	; means  Hit

; near_mode of computer:
left_upper_cell		equ .1
upper_cell			equ	.2
right_upper_cell	equ	.3
right_cell			equ .4
right_bottom_cell	equ	.5
bottom_cell			equ	.6
left_bottom_cell	equ	.7
left_cell			equ	.8

; gui:
cell_width			equ	.6


print macro string_name		;We will use this macro to print strings to the RS232 port
	movlw   upper string_name
    movwf   TBLPTRU
    movlw   high string_name
	movwf   TBLPTRH
   	movlw   low string_name
	movwf   TBLPTRL
   	call    TXstr_1
 endm


put_in_cell_m Macro row, col, what_to_put
	movlw	row
	movwf	ROW
	movlw	col
	movwf	COL
	movlw	what_to_put
	movwf	WHAT_TO_PUT
	call	set_cell,1
	call	print_board
	endm




; -----------------------------------------
; ****************** MAIN *****************
; -----------------------------------------
Main
	call	clear_all

	call	InitializeActions, 1
	;call	RXbyte
	;call	random_row0to5_col0to7
	;nop
	call	place_submarines_computer, 1

	call	change_turn, 1

	call	place_submarines_user

;	put_in_cell_m .1,.1, comp_sub
;	put_in_cell_m .1,.5, comp_sub
;	put_in_cell_m .4,.0, comp_sub
;	put_in_cell_m .4,.6, comp_sub
;	put_in_cell_m .5,.3, comp_sub
	
;	put_in_cell_m .2,.0, user_sub
;	put_in_cell_m .2,.4, user_sub
;	put_in_cell_m .4,.7, user_sub
;	put_in_cell_m .6,.2, user_sub
;	put_in_cell_m .7,.5, user_sub
;	movlw	.5
;	movwf	HOW_MANY_USER_SUBMARINES_LEFT

	;put_in_cell_m .1,.1, user_sub
	;put_in_cell_m .2,.0, comp_sub

	call	set_first_player

	call	game_loop

	call	end_game

	call	ask_user_what_to_do

	goto	end_code
; -----------------------------------------




; -----------------------------------------
; Clears all previous values from registers
; -----------------------------------------
clear_all
	clrf	TRISD
	clrf	PORTD
	clrf	WREG
	clrf	FSR0
	clrf	TMP
	clrf	TMP1
	clrf	TMP2
	clrf	PRODL
	clrf	ROW
	clrf	COL
	clrf	WHAT_TO_PUT
	clrf	ROW_TMP
	clrf	COL_TMP
	clrf	USER_TURN
	clrf	COMP_TURN
	clrf	ROW_DISTANCE
	clrf	COL_DISTANCE
	clrf	HOW_MANY_COMP_SUBMARINES_LEFT
	clrf	HOW_MANY_USER_SUBMARINES_LEFT
	clrf	SOMEONE_WINS
	clrf	EXCEEDED
	clrf	USER_FOUND_SUB_TO_MOVE
	clrf	COMP_FOUND_SUB_TO_MOVE
	setf	COMP_MOVING_SUB_ROW
	clrf	COMP_MOVING_SUB_COL
	clrf	USER_MOVING_SUB_ROW
	clrf	USER_MOVING_SUB_COL
	clrf	COMP_IN_MODE_NEAR
	clrf	COMP_IN_MODE_NEAR_ROUND_SEARCH
	movlw	.2
	movwf	UPPER_COMMON_ROW
	movlw	.5
	movwf	LOWER_COMMON_ROW
	clrf	RANDOM
	return
; -----------------------------------------



; -----------------------------------------
; Clears terminal screen
; -----------------------------------------
clear_screen
	movlw	.12
	call	TXbyte
	movlw	.13
	call	TXbyte
	return	1
; -----------------------------------------



; -----------------------------------------
; Initialize actions:
; -----------------------------------------
InitializeActions
	call 	USART_INIT 		; Initiatization of USART communication port
	call	clear_screen,1	; Clears terminal screen
	call	init_board,1	; makes the board empty
	call	print_board,1	; prints board to terminal
	call	init_timer,1	; initialize timer for random numbers
	clrf	COMP_MODE		; Initialize COMP_MODE to 0 (means: guessing subs)
	clrf	USER_MODE		; Initialize USER_MODE to 0 (means: guessing subs)
	return	1
; -----------------------------------------






; -----------------------------------------
; Initialize timer for random numbers:
; -----------------------------------------
init_timer
	call	TMR0_init, 1	; reads random number
	;call	RXbyte			; OR RX0byte?
	return
; -----------------------------------------





; -----------------------------------------
; Changes the turn from player to computer 
; and from computer to player:
; -----------------------------------------
change_turn
	decf	USER_TURN
	bz		change_to_computer_turn
	bra		change_to_user_turn
	change_to_computer_turn
		movlw	.1
		movwf	COMP_TURN
		clrf	USER_TURN
		bra		end_change_turn
	change_to_user_turn
		movlw	.1
		movwf	USER_TURN
		clrf	COMP_TURN
		bra		end_change_turn
	end_change_turn
		return
; -----------------------------------------







; -----------------------------------------
; Prints Board to terminal:
; -----------------------------------------
print_board
	call	clear_screen
	print	game_title
	call	print_first_line
	call	print_upper_border
	clrf	ROW
	movlw	rows_number
	movwf	COUNTER_ROWS
	loop_rows_print:
		clrf	COL
		movff	ROW, WREG
		addlw	.48
		call 	TXbyte
		movlw	' '
		call 	TXbyte
		call 	TXbyte
		call	print_cells_seperator
		movlw	cols_number
		movwf	COUNTER_COLS
		loop_columns_print:
			call	get_cell, 1
			
;			; a try for drawing borders:
;			movff	ROW, WREG
;			mullw	rows_number
;			movff	PRODL, WREG
;			addwf	COL,0
;			addlw	.200
;			call	TXbyte
			

			; placing the submarine itself:
			bit_2:
			movlw	' ';'_'
			btfsc	GET_CELL,2
			movlw	.248	;'.'
			call 	TXbyte
			bra		bit_0
			
			bit_0:
			movlw	' ';'_'
			btfsc	GET_CELL,0
			movlw	.1	;.147;	'u'	
			call 	TXbyte
			bra		bit_1

			bit_1:
			movlw	' ';'_'
			btfsc	GET_CELL,1
			movlw	'x'
			call 	TXbyte
			bra		bit_4

			bit_4:
			movlw	' ';'_'
			btfsc	GET_CELL,4
			movlw	.2		;'c'			; uncomment if you want to see comp subs
			call 	TXbyte
			bra		bit_5

			bit_5:
			movlw	' ';'_'
			btfsc	GET_CELL,5
			movlw	'x'
			call 	TXbyte
			bra		bit_6

			bit_6:
			movlw	' ';'_'
			btfsc	GET_CELL,6
			movlw	.249	;','
			call 	TXbyte
			bra		next_cell

		next_cell:
			call	print_cells_seperator

			incf	COL					; COL++
			decfsz	COUNTER_COLS
			bra		loop_columns_print
			call	TXcrlf				; newline
			movlw	rows_number
			addlw	.255				; WREG <-- WREG - 1
			cpfseq	ROW
			call	print_horizontal_border
		incf	ROW					; ROW++
		decfsz	COUNTER_ROWS
		bra	loop_rows_print
	call	print_lower_border
	call	TXcrlf				; newline
	return	1
; -----------------------------------------





; -----------------------------------------
; Initializes Board to be empty:
; -----------------------------------------
init_board
	movlw	b'00000000'
	movwf	WHAT_TO_PUT
	clrf	ROW
	movlw	rows_number
	movwf	COUNTER_ROWS
	loop_rows:
		clrf	COL
		movlw	cols_number
		movwf	COUNTER_COLS
		loop_columns:			
			call	set_cell_init, 1
			incf	COL				; COL++
			decfsz	COUNTER_COLS
			bra		loop_columns
			incf	ROW				; ROW++
		decfsz	COUNTER_ROWS
		bra	loop_rows

	return	1
; -----------------------------------------






; -----------------------------------------
; gets BOARD[<ROW>][<COL>] 
; (returns answer in GET_CELL)
; -----------------------------------------
get_cell		; uses ROW, COL
	movlb	0					; set bank0
	lfsr	0, 0x500			; FSRO = 0x500 (Beginning of Board)
	clrf	TMP					; TMP = 0
	movf	ROW,0				; WREG <-- ROW
	mullw	rows_number			; PRODL <-- ROW*8
	movf	PRODL,0				; WREG <-- ROW*8
	addwf	COL, 0				; WREG <-- ROW*8 + COL

	movff	PLUSW0, GET_CELL	; WREG <-- BORAD[ROW*8+COL]
	return	1
; -----------------------------------------






; -----------------------------------------
; puts <WHAT_TO_PUT> in BOARD[<ROW>][<COL>]
; -----------------------------------------
set_cell_init		; uses ROW, COL, WHAT_TO_PUT
	movlb	5					; set bank5
	lfsr	0, 0x500			; FSRO = 0x500 (Beginning of Board)
	movff	ROW,WREG			; WREG <-- ROW
	mullw	rows_number			; PRODL <-- ROW*8
	movf	PRODL,0				; WREG <-- ROW*8
	movlb	0					; set bank0
	addwf	COL,0	 			; WREG <-- ROW*8 + COL
	movlb	5					; set bank5
	movff	WHAT_TO_PUT, PLUSW0	; BORAD[ROW*8+COL] <-- WHAT_TO_PUT

	movlb	0
	return	1
; -----------------------------------------







; -----------------------------------------
; puts <WHAT_TO_PUT> in BOARD[<ROW>][<COL>]
; -----------------------------------------
set_cell		; uses ROW, COL, WHAT_TO_PUT
	lfsr	0, 0x500			; FSRO = 0x500 (Beginning of Board)
	movff	ROW,WREG			; WREG <-- ROW
	mullw	rows_number			; PRODL <-- ROW*8
	movf	PRODL,0				; WREG <-- ROW*8
	addwf	COL,0	 			; WREG <-- ROW*8 + COL
	movff	WREG, TMP1

	call	get_cell,1
	
	movff	GET_CELL, WREG		; WREG <-- GET_CELL
	iorwf	WHAT_TO_PUT			; WHAT_TO_PUT <-- WHAT_TO_PUT | GET_CELL
	movff	TMP1, WREG
	movff	WHAT_TO_PUT, PLUSW0	; BORAD[ROW*8+COL] <-- WHAT_TO_PUT
	
	end_set_cell:
	movlb	0
	return	1
; -----------------------------------------





; -----------------------------------------
; computer places his submarines <WHAT_TO_PUT> in BOARD[<ROW>][<COL>]
; -----------------------------------------
place_submarines_computer
	movlw	true
	movwf	COMP_TURN						; COMP_TURN <-- true
	movlw	initial_number_of_submarines	; (5)
	movwf	SUBMARINES_COMP_COUNTER
	
	print	help_comp_to_place_sub
	clrf	WREG
	try_to_place_submarine
		call	check_if_only_one_left_to_place	; if only one sub left WREG will be 1
		decfsz	WREG
		bra		psc_continue
		bra		comp_finished_placing
		psc_continue:
		call	get_submarine_from_comp
		call	is_valid					; if valid, WREG will be 1
		;if wreg == 1
		decfsz	WREG
		bra		again_comp
		call	place_submarine				; write new sub to memory
		print	help_comp_to_place_sub
		clrf	WREG
		decfsz	SUBMARINES_COMP_COUNTER
	again_comp
		bra		try_to_place_submarine
		;if SUBMARINES_COMP_COUNTER == 0
		bnz		comp_finished_placing

	comp_finished_placing
	call	print_board
	return 1 
; -----------------------------------------



; -----------------------------------------
; Places a computer submarine.
; -----------------------------------------
place_submarine
	call	set_cell,1
	incf	HOW_MANY_COMP_SUBMARINES_LEFT
	call	print_board
	return
; -----------------------------------------



; -----------------------------------------
; Checks if computer can place his last submarine.
; If it can, the sub is placed. If not, message about that is displayed.
; -----------------------------------------
check_if_only_one_left_to_place
	movlw	.1
	cpfseq	SUBMARINES_COMP_COUNTER		; if only one sub left to place, then skip
	bra		more_than_one_left
	bra		only_one_left
	
	more_than_one_left:
		movlw	false
		return

	only_one_left:
	; if only one left to place:
	clrf	ROW
	movlw	rows_number
	addlw	.254					; WREG <-- WREG - 2
	movwf	COUNTER_ROWS
	ciooltp_loop_rows:
		clrf	COL
		movlw	cols_number
		movwf	COUNTER_COLS
		ciooltp_loop_columns:			
			call	is_valid
			decfsz	WREG
			; if not valid:
			bra		ciooltp_continue_check
			; if valid:
			call	place_submarine
			decf	SUBMARINES_COMP_COUNTER
			movlw	true
			return
			
			ciooltp_continue_check:
			incf	COL				; COL++
			decfsz	COUNTER_COLS
			bra		ciooltp_loop_columns
			incf	ROW				; ROW++
		decfsz	COUNTER_ROWS
		bra	ciooltp_loop_rows
	; if the code reached here, that means: there's no valid cell for the 5th
	; submarine. Therefore, computer will display a message saying that it
	; will only place 4 submarines.
	decf	SUBMARINES_COMP_COUNTER
	print	comp_will_place_only_4_subs
	call	Delay
	call	Delay
	call	Delay
	movlw	true					; WREG <-- true
	return	
; -----------------------------------------



; -----------------------------------------
; user places his submarines <WHAT_TO_PUT> in BOARD[<ROW>][<COL>]
; -----------------------------------------
place_submarines_user
	movlw	initial_number_of_submarines	; (5)
	movwf	SUBMARINES_USER_COUNTER
	
	clrf	WREG
	
	bra		try_to_place_submarine_user
	
	again_user_not_first_time
		print	location_is_not_valid
		call	Delay, 1
		call	print_board
	try_to_place_submarine_user
		movlw	.1
		cpfsgt	SUBMARINES_USER_COUNTER
		bra		last_sub
		bra		not_last_sub
		
		last_sub:
		print	do_you_want_to_place_last_sub
		call	get_valid_yes_or_no
		call	TXbyte
		movff	WREG, TMP
		movlw	'y'
		cpfseq	TMP
		bra		doesnt_want_last_sub
		call	print_board
		bra		not_last_sub
		
		doesnt_want_last_sub:
		call	print_board
		call	check_if_no_place_for_last_sub		; if no place, then WREG <-- true
		decf	WREG
		bz		user_finished_placing
		bra		user_is_wrong_end_game

		not_last_sub:
		call	get_submarine_from_user
		call	is_valid
		;if wreg == 1
		decfsz	WREG
		bra		again_user_not_first_time
		print	location_is_valid
		call	set_cell,1
		incf	HOW_MANY_USER_SUBMARINES_LEFT
		call	Delay, 1
		call	print_board
		clrf	WREG
		decfsz	SUBMARINES_USER_COUNTER
	again_user
		bra		try_to_place_submarine_user
		;if SUBMARINES_USER_COUNTER == 0
		bnz		user_finished_placing

	user_finished_placing
	return 1 
; -----------------------------------------



; -----------------------------------------
; Game ends bacause user was wrong about his ability 
; to place his last submarine on board.
; -----------------------------------------
user_is_wrong_end_game
	print	user_is_wrong
	print	computer_wins_msg
	call	Delay
	call	Delay
	call	Delay
	call	Delay
	bra		ask_user_what_to_do
; -----------------------------------------



; -----------------------------------------
; Checks if user truely cannot place his last submarine.
; if truely no place, then WREG <-- 1, else WREG <-- 0.
; -----------------------------------------
check_if_no_place_for_last_sub
	movff	UPPER_COMMON_ROW, ROW		;(2)
	movlw	rows_number
	addlw	.254
	movwf	COUNTER_ROWS
	cinpfls_loop_rows:
		clrf	COL
		movlw	cols_number
		movwf	COUNTER_COLS
		cinpfls_loop_cols:
			call	is_valid
			decfsz	WREG
			; if not valid:
			bra		cinpfls_continue_check
			; if valid:
			movlw	false
			return
			
			cinpfls_continue_check:
			incf	COL					; COL++
			decfsz	COUNTER_COLS
			bra		cinpfls_loop_cols
		incf	ROW						; ROW++
		decfsz	COUNTER_ROWS
		bra		cinpfls_loop_rows
	; if the code reached here, that means: all places were not valid
	; and therefore user was right. User will display a message saying
	; that he'll only place 4 submarines, and the game will continue.
	decf	SUBMARINES_USER_COUNTER
	print	user_will_place_only_4_subs
	movlw	true
	return
; -----------------------------------------




; -----------------------------------------
; checks if <SUB_TO_CHECK> is in valid distance from other sub
; if placing is valid,	then: WREG <-- 1
;						else: WREG <-- 0
; -----------------------------------------
is_valid	; uses SUB_TO_CHECK
	movlw	0
	; 1. submarine isn't on any other submarine.
	; 2. submarine is in the player's area.
	; 3. submarine's distance from any other submarine
	;	 is more than 2 according to Pitagoras.
	; 4. empty at the moment. ready for additions.
	
	clrf	VALIDATION

	validate_1
		call	get_cell					; GET_CELL <-- Board[ROW][COL]
		movlw	.1
		cpfseq	COMP_TURN
		bra		check_if_on_user_submarine
		bra		check_if_on_comp_submarine
		check_if_on_comp_submarine
			btfss	GET_CELL, 4				; if bit4 of GET_CELL is set, then skip
			bra		on_other_sub_check_ok	; meaning: valid
			bra		validate_end			; meaning: NOT valid
		check_if_on_user_submarine
			btfss	GET_CELL, 0				; if bit0 of GET_CELL is set, then skip
			bra		on_other_sub_check_ok	; meaning: valid
			bra		validate_end			; meaning: NOT valid
		on_other_sub_check_ok
			bsf		VALIDATION,0			; VALIDATION<1> <-- 1

	validate_2
		decf	COMP_TURN
		bz		check_if_in_computer_area
		bra		check_if_in_user_area
		check_if_in_computer_area
			incf	COMP_TURN				; returning COMP_TURN to what it was
			movlw	.5						; WREG <-- 5
			cpfsgt	ROW						; if ROW > 5 then skip
			bra		area_check_ok			; meaning: valid
			bra		validate_end			; meaning: NOT valid
		check_if_in_user_area
			incf	COMP_TURN				; returning COMP_TURN to what it was
			movlw	.2						; WREG <-- 2
			cpfslt	ROW						; if ROW < 2 then skip
			bra		area_check_ok			; meaning: valid
			bra		validate_end			; meaning: NOT valid	
		area_check_ok
			bsf		VALIDATION,1			; VALIDATION<1> <-- 1

	validate_3
		movff	ROW,ROW_TMP
		movff	COL,COL_TMP

		;start loop:
		clrf	ROW
		movlw	rows_number
		movwf	COUNTER_ROWS_1
		loop_rows_validate_3:
			clrf	COL
			movlw	cols_number
			movwf	COUNTER_COLS_1
			loop_columns_validate_3:
				call	get_cell			; GET_CELL <-- Board[ROW][COL]
				;;; begin checking for this cell:
				movff	WHAT_TO_PUT, WREG	; WREG <-- WHAT_TO_PUT
				andwf	GET_CELL,0			; WREG <-- WHAT_TO_PUT & GET_CELL
				bz		continue_check		; if WREG = 0 then it means that 
											; WHAT_TO_PUT and GET_CELL are of
											; different players'.

				call	get_distance_between_rows,1
				movff	ROW_DISTANCE, WREG	; WREG <-- ROW_DISTANCE
				mulwf	ROW_DISTANCE		; PRODL <-- ROW_DISTANCE^2
				movff	PRODL, ROW_DISTANCE	; ROW_DISTANCE <-- ROW_DISTANCE^2
				
				call	get_distance_between_columns,1
				movff	COL_DISTANCE, WREG	; WREG <-- COL_DISTANCE
				mulwf	COL_DISTANCE		; PRODL <-- COL_DISTANCE^2
				movff	PRODL, COL_DISTANCE	; COL_DISTANCE <-- COL_DISTANCE^2

				; Pitagoras calculation:
				movff	ROW_DISTANCE, WREG	; WREG <-- ROW_DISTANCE^2
				addwf	COL_DISTANCE,0		; WREG <-- ROW_DISTANCE^2 + COL_DISTANCE^2
				movwf	TMP					; TMP <-- WREG
				movlw	.9					; WREG <-- 9
				cpfsgt	TMP					; if TMP > 9 then skip
				
				bra		validate_3_end		; if TMP < 9 then: NOT valid

				continue_check:
				;;; end of checking for this cell.
				incf	COL					; COL++
				decfsz	COUNTER_COLS_1
				bra		loop_columns_validate_3
				incf	ROW					; ROW++
			decfsz	COUNTER_ROWS_1
			bra	loop_rows_validate_3
		; if the code reached here, then it means that distance from
		; all submarines was valid:
		bsf		VALIDATION,2				; VALIDATION<2> <-- 1
		movff	ROW_TMP, ROW				; return ROW to its original value
		movff	COL_TMP, COL				; return COL to its original value
		bra		validate_4
		
		validate_3_end:
			movff	ROW_TMP, ROW			; return ROW to its original value
			movff	COL_TMP, COL			; return COL to its original value
			bra		validate_end
		
	validate_4:
		bsf		VALIDATION,3				; VALIDATION<3> <-- 1
	
	validate_end
		incf	VALIDATION					; VALIDATION <-- VALIDATION + 1
		movlw	0x0F						; WREG <-- 00001111
		andwf	VALIDATION					; VALIDATION <-- VALIDATION & WREG
		bz		set_all_valid
		bra		set_not_all_valid
	set_all_valid
		movlw	true
		bra		valid_return
	set_not_all_valid
		movlw	false
		bra		valid_return
	valid_return
		
		return
; -----------------------------------------





; -----------------------------------------
; Calculates the distance between ROW and 
; ROW_TMP. returns answer in ROW_DISTANCE.
; -----------------------------------------
get_distance_between_rows
	clrf	ROW_DISTANCE		; ROW_DISTANCE <-- 0
	movff	ROW, ROW_TMP1
	movff	ROW_TMP, WREG		; WREG <-- ROW_TMP
	cpfseq	ROW_TMP1			; if ROW = ROW_TMP then skip
	bra		rows_not_equal
	row_tmp_is_equal_to_row:
		movlw	.0
		movwf	ROW_DISTANCE	; ROW_DISTANCE <-- 0
		bra		end_of_row_distance
	rows_not_equal:
	cpfsgt	ROW_TMP1			; if ROW > ROW_TMP then skip
	bra		row_tmp_is_bigger_than_row
	bra		row_is_bigger_than_row_tmp

	row_tmp_is_bigger_than_row:
		movff	ROW_TMP, WREG
		cpfslt	ROW_TMP1
		bra		end_of_row_distance
		incf	ROW_TMP1
		incf	ROW_DISTANCE
		bra		row_tmp_is_bigger_than_row
		
	row_is_bigger_than_row_tmp:
		movff	ROW_TMP, WREG
		cpfsgt	ROW_TMP1
		bra		end_of_row_distance
		decf	ROW_TMP1
		incf	ROW_DISTANCE
		bra		row_is_bigger_than_row_tmp
		
	end_of_row_distance
		return
; -----------------------------------------


go_to_Main
	bra		Main


; -----------------------------------------
; Calculates the distance between COL and 
; COL_TMP. returns answer in COL_DISTANCE.
; -----------------------------------------
get_distance_between_columns
	clrf	COL_DISTANCE		; COL_DISTANCE <-- 0
	movff	COL, COL_TMP1
	movff	COL_TMP, WREG		; WREG <-- COL_TMP
	cpfseq	COL_TMP1			; if COL = COL_TMP then skip
	bra		columns_not_equal
	col_tmp_is_equal_to_col:
		movlw	.0
		movwf	COL_DISTANCE	; COL_DISTANCE <-- 0
		bra		end_of_col_distance
	columns_not_equal:
	cpfsgt	COL_TMP1			; if COL > COL_TMP then skip
	bra		col_tmp_is_bigger_than_col
	bra		col_is_bigger_than_col_tmp

	col_tmp_is_bigger_than_col:
		movff	COL_TMP, WREG
		cpfslt	COL_TMP1
		bra		end_of_col_distance
		incf	COL_TMP1
		incf	COL_DISTANCE
		bra		col_tmp_is_bigger_than_col
		
	col_is_bigger_than_col_tmp:
		movff	COL_TMP, WREG
		cpfsgt	COL_TMP1
		bra		end_of_col_distance
		decf	COL_TMP1
		incf	COL_DISTANCE
		bra		col_is_bigger_than_col_tmp
		
	end_of_col_distance
		return	1
; -----------------------------------------






; -----------------------------------------

; -----------------------------------------
get_submarine_from_user
	print	request_from_user

	print	row_request
	call	get_valid_digit		; get digit from 0 to 7
	call	TXbyte
	addlw	.208				; change from char value to real value
	movwf	ROW
	
	print	column_request
	call	get_valid_digit		; get digit from 0 to 7
	call	TXbyte
	addlw	.208				; change from char value to real value	
	movwf	COL

	movlw	user_sub
	movwf	WHAT_TO_PUT

	return
; -----------------------------------------	





; -----------------------------------------	
; Gets a random number when any key is hit.
; Returns this number in TMR0L.
; -----------------------------------------
get_random
	clrf	R0Xfl
	call	RX0byte
	decfsz	R0Xfl
	bra		get_random
	movff	TMR0L, RANDOM
	return
; -----------------------------------------	




; -----------------------------------------
; returns random number between 0 to 7 in register TMR0L.
; -----------------------------------------
random_between_0to7
	movff	TMR0L, TMP		; TMP <-- TMR0L
	movlw	b'00000111'		; WREG <-- 00000111
	andwf	TMP				; TMP <-- TMR0L & 00000111
	movff	TMP, RANDOM		; RANDOM <-- TMP

	return
; -----------------------------------------




; -----------------------------------------
; returns random number between 0 to 5 in RANDOM.
; -----------------------------------------
random_between_0to5

	call	get_random				; RANDOM <-- some random number (using TMR0L)
	
	movlw	b'00000011'
	andwf	RANDOM					; RANDOM <-- RANDOM AND '00000011'
	; Now, RANDOM is a number between 0 to 3 (not 0 to 5 yet)

	movff	RANDOM, TMP				; RANDOM <-- TMP
	movlw	b'00000010'				; WREG <-- '00000010'
	andwf	TMP						; TMP <-- TMP AND '00000010'
	rrncf	TMP						; shift right TMP
	decfsz	TMP
	bra		can_add_bit2			; meaning: it could be 5
	bra		end_random_between_0to5	; meaning: it could not be 5
		
	can_add_bit2					; sets bit 2 in RANDOM in probability 0.5
		movlw	b'00000001'
		andwf	TMR0L, 0			; WREG <-- right bit of TMR0L
		decfsz	WREG
		bsf		RANDOM, 2			; RANDOM<2> <-- 1
		
	end_random_between_0to5
		return
; -----------------------------------------




; -----------------------------------------
; returns random number between 2 to 7 in register TMR0L.
; -----------------------------------------
random_between_2to7
	movff	TMR0L, TMP			; TMP <-- TMR0L
	movlw	b'00000111'
	andwf	TMP					; TMP <-- TMR0L & 00000111
	movlw	.1
	nop
	cpfsgt	TMP
	bra		random_between_2to7
	movff	TMP, RANDOM

	return
; -----------------------------------------



; -----------------------------------------
; Creat a random place for next submarine to be placed
; (for computer's subs placing stage)
; -----------------------------------------
get_submarine_from_comp
	
	call	random_between_0to5		; RANDOM <-- num between 0 to 5
	movff	RANDOM, ROW				; ROW <-- RANDOM
	call	random_between_0to7		; RANDOM <-- num between 0 to 7
	movff	RANDOM, COL				; COL <-- RANDOM
	
	movlw	comp_sub				; WREG <-- b'00010000'
	movwf	WHAT_TO_PUT				; WHAT_TO_PUT <-- b'00010000'

	return
; -----------------------------------------





; -----------------------------------------
; Sets who is first player randomly:
; -----------------------------------------
set_first_player
	clrf	COMP_TURN
	clrf	USER_TURN
	movff	TMR0L, TMP
	movlw	.1
	andwf	TMP
	cpfseq	TMP
	bra		user_turn
	bra		comp_turn
	user_turn
		bsf		USER_TURN,0
		print	user_starts
		bra		end_turn
	comp_turn
		bsf		COMP_TURN,0
		print	comp_starts
		bra		end_turn
	end_turn
		call	Delay
		call	Delay
		call	Delay
		call	print_board
		return
; -----------------------------------------




; -----------------------------------------
; main loop of the game in which computer and user
; are trying to guess each other's submarines' locations:
; -----------------------------------------
game_loop
	movlw	.1
	cpfseq	COMP_TURN
	bra		user_plays
	bra		computer_plays
	
	user_plays:
		movlw	.0
		cpfseq	USER_MODE				; checks mode of playing
		bra		user_plays_move_sub		; (guessing or moving
		bra		user_plays_guess_subs	; submarine)

		user_plays_guess_subs:
		call	user_make_a_guess
		call	get_feedback_user
		call	print_feedback
		call	user_change_mode_if_needed
		bra		end_iteration
		
		user_plays_move_sub:
		call	user_move_sub
		bra		end_iteration

	computer_plays:
		movlw	.0
		cpfseq	COMP_MODE				; checks mode of playing
		bra		comp_plays_move_sub		; (guessing or moving
		bra		comp_plays_guess_subs	; submarine)

		comp_plays_guess_subs:
		call	comp_make_a_guess
		call	get_feedback_comp
		call	print_feedback
		call	comp_change_mode_if_needed
		bra		end_iteration

		comp_plays_move_sub:
		call	comp_move_sub
		bra		end_iteration


	end_iteration:
	call	Delay, 1
	call	Delay, 1
	;call	Delay, 1
	;call	Delay, 1
	call	print_board
	call	change_turn
	call	check_if_someone_wins
	movff	SOMEONE_WINS, TMP
	decfsz	TMP						; if someone wins, then skip
	bra		game_loop
	
	return
; -----------------------------------------




; -----------------------------------------
; Taking guess from computer. returns answer in ROW & COL:
; -----------------------------------------
comp_make_a_guess
	print	guess_from_comp

	movlw	true				
	cpfseq	COMP_IN_MODE_NEAR	; if COMP_IN_MODE_NEAR = true, then
	bra		random_mode			; act in "near_mode", else
	bra		near_mode			; act in "random_mode"
	
	; if computer got a "near" feedback, guess 
	; something around this square:
	near_mode:
		_left_upper:
		movlw	left_upper_cell
		cpfseq	COMP_IN_MODE_NEAR_ROUND_SEARCH
		bra		_upper
		incf	COMP_IN_MODE_NEAR_ROUND_SEARCH
		movff	COMP_LAST_GUESS_ROW, ROW
		movff	COMP_LAST_GUESS_COL, COL
		decf	ROW							; ROW--
		decf	COL							; COL--
		call	skip_this_cell_maybe		; if it's better to skip, WREG <-- true
		decf	WREG
		bz		_upper						; if it's better to skip, try next cell
		bra		get_submarine_from_comp_end	; if not skipped, stay with this 
											; ROW and COL, and try to hit them.
		_upper:
		movlw	upper_cell
		cpfseq	COMP_IN_MODE_NEAR_ROUND_SEARCH
		bra		_right_upper
		incf	COMP_IN_MODE_NEAR_ROUND_SEARCH
		movff	COMP_LAST_GUESS_ROW, ROW
		movff	COMP_LAST_GUESS_COL, COL
		decf	ROW							; ROW--
		call	skip_this_cell_maybe		; if it's better to skip, WREG <-- true
		decf	WREG
		bz		_right_upper				; if contains, try next cell
		bra		get_submarine_from_comp_end	; if not exceeded, stay with this 
											; ROW and COL, and try to hit them.

		_right_upper:
		movlw	right_upper_cell
		cpfseq	COMP_IN_MODE_NEAR_ROUND_SEARCH
		bra		_right
		incf	COMP_IN_MODE_NEAR_ROUND_SEARCH
		movff	COMP_LAST_GUESS_ROW, ROW
		movff	COMP_LAST_GUESS_COL, COL
		decf	ROW							; ROW--
		incf	COL							; COL++
		call	skip_this_cell_maybe		; if it's better to skip, WREG <-- true
		decf	WREG
		bz		_right						; if it's better to skip, try next cell
		bra		get_submarine_from_comp_end	; if not skipped, stay with this 
											; ROW and COL, and try to hit them.

		_right:
		movlw	right_cell
		cpfseq	COMP_IN_MODE_NEAR_ROUND_SEARCH
		bra		_right_bottom
		incf	COMP_IN_MODE_NEAR_ROUND_SEARCH
		movff	COMP_LAST_GUESS_ROW, ROW
		movff	COMP_LAST_GUESS_COL, COL
		incf	COL							; COL++
		call	skip_this_cell_maybe		; if it's better to skip, WREG <-- true
		decf	WREG
		bz		_right_bottom				; if it's better to skip, try next cell
		bra		get_submarine_from_comp_end	; if not skipped, stay with this 
											; ROW and COL, and try to hit them.

		_right_bottom:
		movlw	right_bottom_cell
		cpfseq	COMP_IN_MODE_NEAR_ROUND_SEARCH
		bra		_bottom
		incf	COMP_IN_MODE_NEAR_ROUND_SEARCH
		movff	COMP_LAST_GUESS_ROW, ROW
		movff	COMP_LAST_GUESS_COL, COL
		incf	ROW							; ROW++
		incf	COL							; COL++
		call	skip_this_cell_maybe		; if it's better to skip, WREG <-- true
		decf	WREG
		bz		_bottom						; if it's better to skip, try next cell
		bra		get_submarine_from_comp_end	; if not skipped, stay with this 
											; ROW and COL, and try to hit them.

		_bottom:
		movlw	bottom_cell
		cpfseq	COMP_IN_MODE_NEAR_ROUND_SEARCH
		bra		_left_bottom
		incf	COMP_IN_MODE_NEAR_ROUND_SEARCH
		movff	COMP_LAST_GUESS_ROW, ROW
		movff	COMP_LAST_GUESS_COL, COL
		incf	ROW							; ROW++
		call	skip_this_cell_maybe		; if it's better to skip, WREG <-- true
		decf	WREG
		bz		_left_bottom				; if it's better to skip, try next cell
		bra		get_submarine_from_comp_end	; if not skipped, stay with this 
											; ROW and COL, and try to hit them.

		_left_bottom:
		movlw	left_bottom_cell
		cpfseq	COMP_IN_MODE_NEAR_ROUND_SEARCH
		bra		_left
		incf	COMP_IN_MODE_NEAR_ROUND_SEARCH
		movff	COMP_LAST_GUESS_ROW, ROW
		movff	COMP_LAST_GUESS_COL, COL
		incf	ROW							; ROW++
		decf	COL							; COL--
		call	skip_this_cell_maybe		; if it's better to skip, WREG <-- true
		decf	WREG
		bz		_left						; if it's better to skip, try next cell
		bra		get_submarine_from_comp_end	; if not skipped, stay with this 
											; ROW and COL, and try to hit them.

		_left:
		movlw	left_cell
		cpfseq	COMP_IN_MODE_NEAR_ROUND_SEARCH
		bra		random_mode
		incf	COMP_IN_MODE_NEAR_ROUND_SEARCH
		movff	COMP_LAST_GUESS_ROW, ROW
		movff	COMP_LAST_GUESS_COL, COL
		decf	COL							; COL--
		call	skip_this_cell_maybe		; if it's better to skip, WREG <-- true
		decf	WREG
		bz		random_mode					; if it's better to skip, try next cell
		bra		get_submarine_from_comp_end	; if not skipped, stay with this 
											; ROW and COL, and try to hit them.



	random_mode:
		movlw	.6
		movwf	RANDOM_TRIES

		random_mode_try_again:
			decf	RANDOM_TRIES
			bz		random_plan_b

			call	random_between_2to7
			movff	RANDOM, ROW
			
			call	RXbyte
			call	random_between_0to7
			movff	RANDOM, COL
			
			call	skip_this_cell_maybe		; if it's better to skip, WREG <-- true
			decf	WREG
			bz		random_mode_try_again
			bra		get_submarine_from_comp_end

		random_plan_b:
			clrf	ROW
			movlw	rows_number
			movwf	COUNTER_ROWS
			loop_rows_random_plan_b:
				clrf	COL
				movlw	cols_number
				movwf	COUNTER_COLS
				loop_cols_random_plan_b:
					call	skip_this_cell_maybe	; if it's better to skip, WREG <-- true
					decf	WREG
					bnz		get_submarine_from_comp_end		; means: break loop
					incf	COL								; COL++
					decfsz	COUNTER_COLS
					bra		loop_cols_random_plan_b
				incf	ROW									; ROW++
				decfsz	COUNTER_ROWS
				bra		loop_rows_random_plan_b

	get_submarine_from_comp_end:
		call	print_comp_guess
		; mark in memory that this cell was guessed by computer:
		movlw	comp_guess
		movwf	WHAT_TO_PUT
		call	set_cell, 1
		; if last round cell was checked, return to 'random mode':
		movlw	left_cell
		cpfsgt	COMP_IN_MODE_NEAR_ROUND_SEARCH
		return
		clrf	COMP_IN_MODE_NEAR
		return
; -----------------------------------------





; -----------------------------------------
; new random between 0 to 63.
; Generate ROW betwwen 0 to 7, COL between 0 to 7.
; -----------------------------------------
random_row0to7_col0to7
	movff	TMR0L, RANDOM
	clrf	ROW
	clrf	COL
	
	a_0to7:
		movlw	rows_number		; WREG <-- rows_number
		mullw	cols_number		; PRODL <-- rows_number * cols_number
		movff	PRODL, WREG		; WREG <-- 64
		cpfslt	RANDOM			; if RANDOM < 64, then break loop
		bra		a_0to7_again
		bra		b_0to7
		a_0to7_again:
			movlw	.248
			addwf	RANDOM		; RANDOM <-- RANDOM - 8
			bra		a_0to7
		
	b_0to7:
		movlw	rows_number		; 
		cpfslt	RANDOM			; if RANDOM < 8, then break loop
		bra		b_0to7_again
		bra		end_0to7
		b_0to7_again:
			incf	ROW			; ROW++
			movlw	.248		; 
			addwf	RANDOM		; RANDOM <-- RANDOM - 8
			bra		b_0to7
	
	end_0to7:
		movff	RANDOM, COL
	return
; -----------------------------------------


; -----------------------------------------
; new random between 0 to 63.
; Generate ROW betwwen 0 to 7, COL between 0 to 7.
; -----------------------------------------
random_row0to5_col0to7
	movff	TMR0L, RANDOM
	clrf	ROW
	clrf	COL
	
	a_0to5:
		movlw	rows_number
		decf	WREG
		decf	WREG			; WREG <-- rows_number-2
		mullw	cols_number		; PRODL <-- (rows_number-2) * cols_number
		movff	PRODL, WREG		; WREG <-- 48
		cpfslt	RANDOM			; if RANDOM < 48, then break loop
		bra		a_0to5_again
		bra		b_0to5
		a_0to5_again:
			movlw	.248
			addwf	RANDOM		; RANDOM <-- RANDOM - 8
			bra		a_0to5
		
	b_0to5:
		movlw	rows_number		; 
		cpfslt	RANDOM			; if RANDOM < 8, then break loop
		bra		b_0to5_again
		bra		end_0to5
		b_0to5_again:
			incf	ROW			; ROW++
			movlw	.248		; 
			addwf	RANDOM		; RANDOM <-- RANDOM - 8
			bra		b_0to5
	
	end_0to5:
		movff	RANDOM, COL
	return
; -----------------------------------------



; -----------------------------------------
; Asks user if he would want to play again.
; -----------------------------------------
ask_user_what_to_do
	print	play_again?
	call	get_valid_yes_or_no
	call	TXbyte
	movff	WREG, TMP
	movlw	'y'
	cpfseq	TMP				; if TMP equals 'y', then skip
	bra		middle_code
	call	Delay, 1
	bra		go_to_Main
	
	return
; -----------------------------------------



; -----------------------------------------
; Gets from user a digit between 0 to 7 only.
; -----------------------------------------
get_valid_yes_or_no
	call	RXbyte
	movff	WREG, TMP
	movlw	'y'
	cpfseq	TMP
	bra		get_valid_yes_or_no
	movlw	'n'
	cpfseq	TMP
	bra		get_valid_yes_or_no
	
	movff	TMP, WREG
	return
; -----------------------------------------



; -----------------------------------------
; Checks if it's better to skip this cell from couple of reasons:
; 		check 1: ROW or COL exceeded board's border.
; 		check 2: Board[ROW][COL] has a computer submarine in it.
;		check 3: Checks if comp has guessed this cell, and got 'miss'.
;		check 4: 2 upper lines check.
;		check 5: Checks if this cell contains a hit user submarine.
; -----------------------------------------
skip_this_cell_maybe
	; 1. check if this cell exceeded:
	call	is_exceeded_board			; if exceeded, EXCEEDED <-- true
	decf	EXCEEDED
	bz		skip_it						; if exceeded, try next cell
	; 2. check if this cell contains another sub:
	call	is_contain_comp_submarine_only	; if contains, WREG <-- true
	decf	WREG
	bz		skip_it						; if contains, try next cell
	; 3. check if this cell was checked before and marked as 'miss':
	call	get_cell
	btfsc	GET_CELL, 7
	bra		skip_it						; if missed already, try next cell
	; 4. check if this cell is in the 2 upper lines (comp area):
	movlw	.1
	cpfsgt	ROW
	bra		skip_it						; if ROW is 0 or 1, try next cell
	; 5. check if this cell contains a hit user submarine:
	call	is_contain_a_hit_user_submarine	; if contains, WREG <-- true
	decf	WREG
	bz		skip_it						; if contains, try next cell

	bra		dont_skip_it

	skip_it
		movlw	true
		return

	dont_skip_it
		movlw	false
		return
; -----------------------------------------



; -----------------------------------------
; Prints computer's guess
; -----------------------------------------
print_comp_guess
	call	TXcrlf
	
	print	row_request
	movff	ROW, WREG
	addlw	.48
	call	TXbyte
	
	print	column_request
	movff	COL, WREG
	addlw	.48
	call	TXbyte
	
	return
; -----------------------------------------
	



; -----------------------------------------
; Taking guess from user. returns answer in ROW & COL:
; -----------------------------------------
user_make_a_guess
	print	guess_from_user

	print	row_request
	call	get_valid_digit
	call	TXbyte
	addlw	.208
	movwf	ROW
	
	print	column_request
	call	get_valid_digit
	call	TXbyte
	addlw	.208
	movwf	COL
	
	; mark in memory that this cell was guessed by user:
	movlw	user_guess
	movwf	WHAT_TO_PUT
	call	set_cell, 1

	return
; -----------------------------------------




middle_code
	bra		end_code




; -----------------------------------------
; Checks if trying to shoot an already shot submarine.
; Returns answer in USER_WAS_HIT_BEFORE or COMP_WAS_HIT_BEFORE, 
; depends if checking for user or for comp, respectively.
; -----------------------------------------
was_it_hit_before
	clrf	USER_WAS_HIT_BEFORE
	clrf	COMP_WAS_HIT_BEFORE
	movff	GET_CELL, USER_WAS_HIT_BEFORE	; USER_WAS_HIT_BEFORE <-- GET_CELL
	movlw	b'00000010'						; WREG <-- 00000010
	andwf	USER_WAS_HIT_BEFORE				; USER_WAS_HIT_BEFORE <-- IS_HIT_USER & 00000010

	movff	GET_CELL, COMP_WAS_HIT_BEFORE	; COMP_WAS_HIT_BEFORE <-- GET_CELL
	movlw	b'00100000'						; WREG <-- 00000010
	andwf	COMP_WAS_HIT_BEFORE				; COMP_WAS_HIT_BEFORE <-- COMP_WAS_HIT_BEFORE & 00000010
	
	return	1
; -----------------------------------------







; -----------------------------------------
; Gives feedback to user, according to his guess
; using this key: FEEDBACK = 0  means  Miss, completely
;				  FEEDBACK = 1  means  Miss, but 1 cell far from hit (may be in any direction)
; 				  FEEDBACK = 2  means  Hit
; -----------------------------------------
get_feedback_user
	clrf	FEEDBACK
	clrf	FEEDBACK_USER
	clrf	WHAT_TO_PUT
	
	movlw	comp_sub				; because user seeks for comp_sub
	movwf	WHAT_TO_LOOK_FOR
	bsf		WHAT_TO_PUT, 5			; WHAT_TO_PUT <-- 00100000
	call	get_cell,1				; GET_CELL <-- Borad[ROW][COL]
	movff	GET_CELL, WREG
	andwf	WHAT_TO_LOOK_FOR,0
	bz		no_hit_user				; 
	hit_now:
		; checking if this submarine has already been hit before:
		call	was_it_hit_before,1
		movlw	.0
		cpfseq	COMP_WAS_HIT_BEFORE
		bra		user_trying_to_hit_a_hit_sub; the hit is not from now
	
		movlw	hit
		movwf	FEEDBACK			; FEDBACK <-- 2
		movwf	FEEDBACK_USER		; FEDBACK_USER <-- 2
		; actions done when hitting a submarine:
		decf	HOW_MANY_COMP_SUBMARINES_LEFT
		movff	GET_CELL, WREG		; WREG <-- GET_CELL
		iorwf	WHAT_TO_PUT			; WHAT_TO_PUT <-- WHAT_TO_PUT | GET_CELL
		call	set_cell,1
		bra		end_feedback_user

	user_trying_to_hit_a_hit_sub
		print	trying_to_hit_a_hit_sub

	no_hit_user
		call	check_if_near
		decfsz	NEAR
		bra		miss_user
		movlw	near
		movwf	FEEDBACK			; FEDBACK <-- 1
		movwf	FEEDBACK_USER		; FEDBACK_USER <-- 1
		bra		end_feedback_user
	
	miss_user
		movlw	miss
		movwf	FEEDBACK			; FEDBACK <-- 0
		movwf	FEEDBACK_USER		; FEDBACK_USER <-- 0
		; mark in memory that this cell was guessed by user, and missed:
		movlw	user_guess_miss
		movwf	WHAT_TO_PUT
		call	set_cell, 1
		bra		end_feedback_user

	end_feedback_user
		return
; -----------------------------------------







; -----------------------------------------
; Gives feedback to user, according to his guess
; using this key: FEEDBACK = 0  means  Miss, completely
;				  FEEDBACK = 1  means  Miss, but 1 cell far from hit (may be in any direction)
; 				  FEEDBACK = 2  means  Hit
; -----------------------------------------
get_feedback_comp
	clrf	FEEDBACK_COMP
	clrf	WHAT_TO_PUT
	
	movlw	user_sub				; because comp seeks for user_sub
	movwf	WHAT_TO_LOOK_FOR
	bsf		WHAT_TO_PUT, 1			; WHAT_TO_PUT <-- 00000010
	call	get_cell,1				; GET_CELL <-- Borad[ROW][COL]
	movff	GET_CELL, WREG
	andwf	WHAT_TO_LOOK_FOR,0
	bz		no_hit_comp				; 
	hit_now_comp:
		; checking if this submarine has already been hit before:
		call	was_it_hit_before,1
		movlw	.0
		cpfseq	USER_WAS_HIT_BEFORE
		bra		comp_trying_to_hit_a_hit_sub; the hit is not from now
	
		movlw	hit
		movwf	FEEDBACK						; FEEDBACK <-- hit      (2)
		movwf	FEEDBACK_COMP					; FEEDBACK_COMP <-- hit
		; actions done when hitting a submarine:
		decf	HOW_MANY_USER_SUBMARINES_LEFT
		movff	GET_CELL, WREG					; WREG <-- GET_CELL
		iorwf	WHAT_TO_PUT						; WHAT_TO_PUT <-- WHAT_TO_PUT | GET_CELL
		call	set_cell,1
		clrf	COMP_IN_MODE_NEAR				; COMP_IN_MODE_NEAR <-- false
		clrf	COMP_IN_MODE_NEAR_ROUND_SEARCH	; COMP_IN_MODE_NEAR_ROUND_SEARCH <-- 0
		bra		end_feedback_comp
	
	comp_trying_to_hit_a_hit_sub
		print	trying_to_hit_a_hit_sub
	
	no_hit_comp
		call	check_if_near
		decfsz	NEAR
		bra		miss_comp
		movlw	near
		movwf	FEEDBACK				; FEEDBACK <-- near		(1)
		movwf	FEEDBACK_COMP			; FEEDBACK_COMP <-- near
		; save last guess, in order to check around it:
		movlw	true				
		cpfseq	COMP_IN_MODE_NEAR		; if COMP_IN_MODE_NEAR = true, then
		bra		change_to_mode_near		; act in "near_mode", else
		bra		already_in_mode_near	; act in "random_mode"

		change_to_mode_near:
			movff	ROW, COMP_LAST_GUESS_ROW	; COMP_LAST_GUESS_ROW <-- ROW
			movff	COL, COMP_LAST_GUESS_COL	; COMP_LAST_GUESS_COL <-- COL
			movlw	true
			movwf	COMP_IN_MODE_NEAR			; COMP_IN_MODE_NEAR <-- true
			movlw	left_upper_cell				; start check around the cell, starting from left_upper_cell
			movwf	COMP_IN_MODE_NEAR_ROUND_SEARCH
			bra		end_feedback_comp
		already_in_mode_near:
			bra		end_feedback_comp
	miss_comp
		movlw	miss
		movwf	FEEDBACK			; FEEDBACK <-- miss		(0)
		movwf	FEEDBACK_COMP		; FEEDBACK_COMP <-- miss
		
		; mark in memory that this cell was guessed by computer, and missed:
		movlw	comp_guess_miss
		movwf	WHAT_TO_PUT
		call	set_cell, 1
		
		bra		end_feedback_comp

	end_feedback_comp
		return
; -----------------------------------------




; -----------------------------------------
; Move most far away computer's submarine upon user's lines.
; On first time the right submarine is chosen and is saved in 
; USER_MOVING_SUB_ROW, 
; -----------------------------------------
user_move_sub
	movlw	false						; WREG <-- false
	cpfseq	USER_FOUND_SUB_TO_MOVE		; if USER_FOUND_SUB_TO_MOVE = 0 
										; (means: user hasn't found yet
										; submarine to move), then skip.
	bra		move_user
	
	; This part will happen only on first time of this function to run:
	clrf	ROW
	movlw	rows_number
	movwf	COUNTER_ROWS
	loop_rows_user_move_sub:
		clrf	COL
		movlw	cols_number
		movwf	COUNTER_COLS
		loop_cols_user_move_sub:
			clrf	GET_CELL
			call	get_cell
			btfsc	GET_CELL, 4
			bra		user_found_sub		; computer submarine is found!
			incf	COL					; COL++
			decfsz	COUNTER_COLS
			bra		loop_cols_user_move_sub
		incf	ROW						; ROW++
		decfsz	COUNTER_ROWS
		bra		loop_rows_user_move_sub
	
	user_found_sub:
		movff	ROW, USER_MOVING_SUB_ROW	; USER_MOVING_SUB_ROW <-- ROW
		movff	COL, USER_MOVING_SUB_COL	; USER_MOVING_SUB_COL <-- COL
		bsf		USER_FOUND_SUB_TO_MOVE, 0	; USER_FOUND_SUB_TO_MOVE <-- 1
		print	user_found_sub_to_move
		movlw	'('
		call	TXbyte
		movff	ROW, WREG
		addlw	.48
		call	TXbyte
		movlw	','
		call	TXbyte
		movff	COL, WREG
		addlw	.48
		call	TXbyte
		movlw	')'
		call	TXbyte
		call	Delay
		call	Delay
		print	newline

	; This part will happen always in this function:
	move_user:
	; delete submarine from previous location:
	print	user_is_moving_sub
	movff	USER_MOVING_SUB_ROW, ROW
	movff	USER_MOVING_SUB_COL, COL
	call	get_cell
	movlw	b'00001111'					; because we don't want to delete a user submarine if it was there.
	andwf	GET_CELL, 0					; WREG <-- WREG & GET_CELL
	movff	WREG, WHAT_TO_PUT			; WHAT_TO_PUT <-- WREG
	call	set_cell_init, 1			; Board[ROW][COL] <-- WHAT_TO_PUT
	
	; Check where to move in this order: 	1. down. if not free:
	;										2. right, if not free:
	;										3. left.
	move_user_try_down:
		movff	USER_MOVING_SUB_ROW, ROW
		movff	USER_MOVING_SUB_COL, COL
		incf	ROW							; move submarine forward (down)
		call	get_cell
		call	is_free_of_submarine		; if there isn't sub, then WREG <-- 1
		decfsz	WREG						; if there isn't sub, then skip
		bra		move_user_try_right			; if there is sub, then try right
		incf	USER_MOVING_SUB_ROW			; USER_MOVING_SUB_ROW++
		bra		move_user_finally			; stop trying other directions

	move_user_try_right:
		movff	USER_MOVING_SUB_ROW, ROW
		movff	USER_MOVING_SUB_COL, COL
		movlw	cols_number					; WREG <-- 8
		decf	WREG						; WREG--
		cpfseq	COL							; if COL = 7 (means: cannot increase), then skip
		incf	COL							; COL++
		call	get_cell
		call	is_free_of_submarine		; if there isn't sub, then WREG <-- 1
		decfsz	WREG						; if there isn't sub, then skip
		bra		move_user_try_left			; if there is sub, then try left
		incf	USER_MOVING_SUB_COL			; USER_MOVING_SUB_COL++
		bra		move_user_finally			; stop trying other directions


	move_user_try_left:
		movff	USER_MOVING_SUB_ROW, ROW
		movff	USER_MOVING_SUB_COL, COL
		movlw	.0							; WREG <-- 0
		cpfseq	COL							; if COL = 0 (means: cannot decrease), then skip
		decf	COL
		call	get_cell
		call	is_free_of_submarine		; if there isn't sub, then WREG <-- 1
		decfsz	WREG						; if there isn't sub, then skip
		bra		move_user_finally			; if there is sub, then (not possible)
		decf	USER_MOVING_SUB_COL			; USER_MOVING_SUB_COL--
		bra		move_user_finally			; stop trying other directions



	move_user_finally:
	; add submarine to next location:
	movff	USER_MOVING_SUB_ROW, ROW
	movff	USER_MOVING_SUB_COL, COL
	movlw	comp_hitted_sub
	movwf	WHAT_TO_PUT
	call	set_cell, 1
	
	return
; -----------------------------------------



; -----------------------------------------
; Move most far away computer's submarine upon user's lines.
; On first time the right submarine is chosen and is saved in 
; USER_MOVING_SUB_ROW, 
; -----------------------------------------
comp_move_sub
	movlw	false						; WREG <-- false
	cpfseq	COMP_FOUND_SUB_TO_MOVE		; if COMP_FOUND_SUB_TO_MOVE = 0 
										; (means: comp hasn't found yet
										; submarine to move), then skip.
	bra		move_comp
	
	; This part will happen only on first time of this function to run:
	movlw	rows_number
	decf	WREG
	movwf	ROW							; ROW <-- 7
	movlw	rows_number
	movwf	COUNTER_ROWS
	loop_rows_comp_move_sub:
		movlw	cols_number
		decf	WREG
		movwf	COL						; COL <-- 7
		movlw	cols_number
		movwf	COUNTER_COLS
		loop_cols_comp_move_sub:
			clrf	GET_CELL
			call	get_cell
			btfsc	GET_CELL, 0
			bra		comp_found_sub		; user submarine is found!
			decf	COL					; COL--
			decfsz	COUNTER_COLS
			bra		loop_cols_comp_move_sub
		decf	ROW						; ROW--
		decfsz	COUNTER_ROWS
		bra		loop_rows_comp_move_sub
	
	comp_found_sub:
		movff	ROW, COMP_MOVING_SUB_ROW	; COMP_MOVING_SUB_ROW <-- ROW
		movff	COL, COMP_MOVING_SUB_COL	; COMP_MOVING_SUB_COL <-- COL
		bsf		COMP_FOUND_SUB_TO_MOVE, 0	; COMP_FOUND_SUB_TO_MOVE <-- 1
		print	comp_found_sub_to_move
		movlw	'('
		call	TXbyte
		movff	ROW, WREG
		addlw	.48
		call	TXbyte
		movlw	','
		call	TXbyte
		movff	COL, WREG
		addlw	.48
		call	TXbyte
		movlw	')'
		call	TXbyte
		call	Delay
		call	Delay
		print	newline

	; This part will happen always in this function:
	move_comp:
	; delete submarine from previous location:
	print	comp_is_moving_sub
	movff	COMP_MOVING_SUB_ROW, ROW
	movff	COMP_MOVING_SUB_COL, COL
	call	get_cell
	movlw	b'11110000'					; because we don't want to delete a user submarine if it was there.
	andwf	GET_CELL, 0					; WREG <-- WREG & GET_CELL
	movff	WREG, WHAT_TO_PUT			; WHAT_TO_PUT <-- WREG
	call	set_cell_init, 1			; Board[ROW][COL] <-- WHAT_TO_PUT
	
	; Check where to move in this order: 	1. down. if not free:
	;										2. left, if not free:
	;										3. right.
	move_comp_try_up:
		movff	COMP_MOVING_SUB_ROW, ROW
		movff	COMP_MOVING_SUB_COL, COL
		decf	ROW							; move submarine forward (up)
		call	get_cell
		call	is_free_of_submarine		; if there isn't sub, then WREG <-- 1
		decfsz	WREG						; if there isn't sub, then skip
		bra		move_comp_try_right			; if there is sub, then try right
		decf	COMP_MOVING_SUB_ROW			; COMP_MOVING_SUB_ROW--
		bra		move_comp_finally			; stop trying other directions

	move_comp_try_left:
		movff	COMP_MOVING_SUB_ROW, ROW
		movff	COMP_MOVING_SUB_COL, COL
		movlw	.0							; WREG <-- 0
		cpfseq	COL							; if COL = 0 (means: cannot decrease), then skip
		decf	COL
		call	get_cell
		call	is_free_of_submarine		; if there isn't sub, then WREG <-- 1
		decfsz	WREG						; if there isn't sub, then skip
		bra		move_comp_try_right			; if there is sub, then (not possible)
		decf	COMP_MOVING_SUB_COL			; COMP_MOVING_SUB_COL--
		bra		move_comp_finally			; stop trying other directions

	move_comp_try_right:
		movff	COMP_MOVING_SUB_ROW, ROW
		movff	COMP_MOVING_SUB_COL, COL
		movlw	cols_number					; WREG <-- 8
		decf	WREG						; WREG--
		cpfseq	COL							; if COL = 7 (means: cannot increase), then skip
		incf	COL							; COL++
		call	get_cell
		call	is_free_of_submarine		; if there isn't sub, then WREG <-- 1
		decfsz	WREG						; if there isn't sub, then skip
		bra		move_comp_finally			; if there is sub, then try left
		incf	COMP_MOVING_SUB_COL			; COMP_MOVING_SUB_COL++
		bra		move_comp_finally			; stop trying other directions



	move_comp_finally:
	; add submarine to next location:
	movff	COMP_MOVING_SUB_ROW, ROW
	movff	COMP_MOVING_SUB_COL, COL
	movlw	user_hitted_sub
	movwf	WHAT_TO_PUT
	call	set_cell, 1
	
	return
; -----------------------------------------



; -----------------------------------------
; Checks if GET_CELL is free of any submarine.
; If it's free WREG <-- 1, else WREG <-- 0.
; -----------------------------------------
is_free_of_submarine
	movlw	.0
	btfsc	GET_CELL, 0
	bra		not_free
	btfsc	GET_CELL, 4
	bra		not_free
	bra		free
	free:
		movlw	true			; if GET_CELL = 0,  WREG <-- true
		bra		end_free_check
	not_free:
		movlw	false			; if GET_CELL != 0, WREG <-- false
		bra		end_free_check
	end_free_check:
		return
; -----------------------------------------





; -----------------------------------------
; Checks if GET_CELL is free of computer submarine ONLY. 
; If it's free WREG <-- 1, else WREG <-- 0. (if it has 
; comp sub and also user sub it will not skip it (WREG <-- 0)).
; -----------------------------------------
is_contain_comp_submarine_only
	call	get_cell
	movlw	b'00010001' ;comp_sub
	movff	GET_CELL, TMP
	andwf	TMP			; TMP <-- GET_CELL & 00010001
	movlw	b'00010000'
	cpfseq	TMP
	bra		not_contains
	bra		contains
	
	contains:
		movlw	true			; if TMP != 0,  WREG <-- true
		bra		end_contains_check
	not_contains:
		movlw	false			; if TMP = 0, WREG <-- false
		bra		end_contains_check
	end_contains_check:
		return
; -----------------------------------------



; -----------------------------------------
; Checks if GET_CELL is free of a HIT user submarine.
; If it's free WREG <-- 1, else WREG <-- 0. (if it has 
; comp sub and also user sub it will not skip it (WREG <-- 0)).
; -----------------------------------------
is_contain_a_hit_user_submarine
	call	get_cell
	movlw	b'00000010' ;	a hitted user sub
	movff	GET_CELL, TMP
	andwf	TMP			; TMP <-- GET_CELL & 00000010
	movlw	b'00000010'
	cpfseq	TMP
	bra		ichus_not_contains
	bra		ichus_contains
	
	ichus_contains:
		movlw	true			; if TMP != 0,  WREG <-- true
		bra		end_ichus_contains_check
	ichus_not_contains:
		movlw	false			; if TMP = 0, WREG <-- false
		bra		end_ichus_contains_check
	end_ichus_contains_check:
		return
; -----------------------------------------



; -----------------------------------------
; Checks if comp finished bombing the user's submarines.
; -----------------------------------------
comp_change_mode_if_needed
	movlw	.0
	cpfsgt	HOW_MANY_USER_SUBMARINES_LEFT	; if HOW_MANY_USER_SUBMARINES_LEFT > 0, then skip
	bsf		COMP_MODE, 0					; COMP_MODE <-- 1
	return
; -----------------------------------------




; -----------------------------------------
; Checks if user finished bombing the comp's submarines.
; -----------------------------------------
user_change_mode_if_needed
	movlw	.0
	cpfsgt	HOW_MANY_COMP_SUBMARINES_LEFT	; if HOW_MANY_COMP_SUBMARINES_LEFT > 0, then skip
	bsf		USER_MODE, 0					; USER_MODE <-- 1
	return
; -----------------------------------------




; -----------------------------------------
; Checks whether one of the cells around Board[ROW][COL}
; are of the enemy (in that case the feedback will be 'near'
; instead of 'miss'. Returns result in NEAR.
; -----------------------------------------
check_if_near
	movff	WHAT_TO_LOOK_FOR, WREG
	movff	ROW, ROW_TMP			; save original value in tmp
	movff	COL, COL_TMP			; save original value in tmp
	clrf	NEAR
	
	up_left:
		decf	ROW
		decf	COL
		call	is_exceeded_board	; check if this cell exceeded board limits
		decf	EXCEEDED			; EXCEEDED--
		bz		up					; go to next check if this cell exceeded board
		call	is_this_non_hit_sub
		decf	WREG
		bnz		up
		incf	NEAR
		bra		end_near

	up:
		incf	COL
		call	is_exceeded_board	; check if this cell exceeded board limits
		decf	EXCEEDED			; EXCEEDED--
		bz		up_right			; go to next check if this cell exceeded board
		call	is_this_non_hit_sub
		decf	WREG
		bnz		up_right
		incf	NEAR
		bra		end_near

	up_right:
		incf	COL
		call	is_exceeded_board	; check if this cell exceeded board limits
		decf	EXCEEDED			; EXCEEDED--
		bz		right				; go to next check if this cell exceeded board
		call	is_this_non_hit_sub
		decf	WREG
		bnz		right
		incf	NEAR
		bra		end_near

	right:
		incf	ROW
		call	is_exceeded_board	; check if this cell exceeded board limits
		decf	EXCEEDED			; EXCEEDED--
		bz		down_right			; go to next check if this cell exceeded board
		call	is_this_non_hit_sub
		decf	WREG
		bnz		down_right
		incf	NEAR
		bra		end_near

	down_right:
		incf	ROW
		call	is_exceeded_board	; check if this cell exceeded board limits
		decf	EXCEEDED			; EXCEEDED--
		bz		down				; go to next check if this cell exceeded board
		call	is_this_non_hit_sub
		decf	WREG
		bnz		down
		incf	NEAR
		bra		end_near

	down:
		decf	COL
		call	is_exceeded_board	; check if this cell exceeded board limits
		decf	EXCEEDED			; EXCEEDED--
		bz		down_left			; go to next check if this cell exceeded board
		call	is_this_non_hit_sub
		decf	WREG
		bnz		down_left
		incf	NEAR
		bra		end_near

	down_left:
		decf	COL
		call	is_exceeded_board	; check if this cell exceeded board limits
		decf	EXCEEDED			; EXCEEDED--
		bz		left				; go to next check if this cell exceeded board
		call	is_this_non_hit_sub
		decf	WREG
		bnz		left
		incf	NEAR
		bra		end_near

	left:
		decf	ROW
		call	is_exceeded_board	; check if this cell exceeded board limits
		decf	EXCEEDED			; EXCEEDED--
		bz		end_near			; go to next check if this cell exceeded board
		call	is_this_non_hit_sub
		decf	WREG
		bnz		end_near
		incf	NEAR
		bra		end_near

	end_near:
	movff	ROW_TMP, ROW
	movff	COL_TMP, COL
	return 	1
; -----------------------------------------
	



; -----------------------------------------
; Checks if this submarine is a user submarine, and that it was never hit before.
; If these 2 conditions are met, WREG <-- 1, else 0.
; -----------------------------------------
is_this_non_hit_sub
	;movff	WHAT_TO_LOOK_FOR, WREG
	;call	get_cell,1			; GET_CELL <-- Board[ROW][COL]
	;andwf	GET_CELL			; GET_CELL <-- GET_CELL & WHAT_TO_LOOK_FOR
	;cpfseq	GET_CELL			; if GET_CELL = WREG (means no enemy sub here), then skip
	movlw	true
	cpfseq	COMP_TURN
	bra		check_non_hit_comp_sub
	bra		check_non_hit_user_sub
	
	check_non_hit_comp_sub:
	call	get_cell,1			; GET_CELL <-- Board[ROW][COL]
	btfss	GET_CELL, 4			; if GET_CELL<4> is 1, then it's a comp sub
	bra		answer_is_no
	btfsc	GET_CELL, 5			; if GET_CELL<5> is 0, then it wasn't hit
	bra		answer_is_no
	bra		answer_is_yes

	check_non_hit_user_sub:
	call	get_cell,1			; GET_CELL <-- Board[ROW][COL]
	btfss	GET_CELL, 0			; if GET_CELL<0> is 1, then it's a user sub
	bra		answer_is_no
	btfsc	GET_CELL, 1			; if GET_CELL<1> is 0, then it wasn't hit
	bra		answer_is_no
	bra		answer_is_yes

	answer_is_no:
		movlw	.0
		return
	answer_is_yes:
		movlw	.1
		return
; -----------------------------------------



; -----------------------------------------
; Checks if ROW, COL in the 'near' check exceeded
; board size. If exceeded, EXCEEDED <-- 1, else 0.
; -----------------------------------------
is_exceeded_board
	clrf	EXCEEDED			; reset EXCEEDED

	movlw	rows_number			; if ROW < rows_number, then continue checking
	cpfslt	ROW
	bra		end_exceeded
	
	movlw	0xFF				; if ROW = 0xFF, then stop checking
	cpfseq	ROW
	bra		check_col_exceeded	; else, continue checking
	bra		end_exceeded

	check_col_exceeded:
	movlw	cols_number			; if COL < cols_number, then continue checking
	cpfslt	COL
	bra		end_exceeded
	
	movlw	0xFF				; if COL = 0xFF, then stop checking
	cpfseq	COL
	bra		end_not_exceeded	; else, finish checking.
	bra		end_exceeded		

	bra		end_not_exceeded

	end_exceeded
		bsf		EXCEEDED, 0
		return
	end_not_exceeded
		return
; -----------------------------------------




; -----------------------------------------
; Prints feedback (general, for comp & user)
; -----------------------------------------
print_feedback
	movlw	.0
	cpfsgt	FEEDBACK
	bra		print_miss
	
	movlw	.1
	cpfsgt	FEEDBACK
	bra		print_near
	print	feedback_hit
	bra		end_print_feedback

	print_miss
	print	feedback_miss
	bra		end_print_feedback

	print_near
	print	feedback_near
	bra		end_print_feedback

	end_print_feedback
	return
; -----------------------------------------






; -----------------------------------------
; Checks if one of the players won. Returns
; answer in <SOMEONE_WINS> (1 if true)
; -----------------------------------------
check_if_someone_wins
	movlw	rows_number
	addlw	.254						; WREG <-- first line of user (WREG <-- WREG-2)
	cpfslt	USER_MOVING_SUB_ROW			; 
	bsf		SOMEONE_WINS, 0				; SOMEONE_WINS <-- 1

	movlw	.1							; WREG <-- first line of computer
	cpfsgt	COMP_MOVING_SUB_ROW			; 
	bsf		SOMEONE_WINS, 0				; SOMEONE_WINS <-- 1

	return
; -----------------------------------------








; -----------------------------------------
; Actions that happen when game is over
; -----------------------------------------
end_game
	
	movlw	rows_number
	addlw	.254						; WREG <-- first line of user (WREG <-- WREG-2)
	cpfslt	USER_MOVING_SUB_ROW			; if user got the moving sub to 
	bra		user_wins					; his first line, user wins.
	
	movlw	.1							; WREG <-- first line of computer
	cpfsgt	COMP_MOVING_SUB_ROW			; if computer got the moving sub to 
	bra		comp_wins					; his first line, computer wins.

	bra		end_wins


	comp_wins:
		print	computer_wins_msg
		bra		end_wins
	
	user_wins:
		print	user_wins_msg
		bra		end_wins	
	
	nop


	end_wins:
	call	Delay, 1
	call	Delay, 1
	call	Delay, 1
	call	Delay, 1
	
	return
; -----------------------------------------




; -----------------------------------------
; Gets from user a digit between 0 to 7 only.
; -----------------------------------------
get_valid_digit
	call	RXbyte
	movff	WREG, TMP
	movlw	.56
	cpfslt	TMP
	bra		get_valid_digit
	movlw	.47
	cpfsgt	TMP
	bra		get_valid_digit
	
	movff	TMP, WREG
	return
; -----------------------------------------




; -----------------------------------------
;	 			GUI FUNCTIOMS
; -----------------------------------------


; -----------------------------------------
; Prints Board's first row to terminal:
; -----------------------------------------
print_first_line
	movlw	cols_number
	movwf	COUNTER_COLS
	movlw	.0
	movwf	TMP
	movlw	' '
	call	TXbyte
	call	TXbyte
	call	TXbyte
	fl:
		movlw	2
		movwf	COUNTER		; COUNTER <-- 2
		fl1_loop:
			movlw	' '		; space
			call	TXbyte
			decfsz	COUNTER
			bra		fl1_loop
		movff	TMP, WREG
		addlw	.48			; convert to ascii
		call	TXbyte
		movlw	cell_width
		addlw	.254		; WREG <-- WREG - 2
		movwf	COUNTER		; COUNTER <-- cell_width - 2
		fl2_loop:
			movlw	' '		; space
			call	TXbyte
			decfsz	COUNTER
			bra		fl2_loop
		incf	TMP
		decf	COUNTER_COLS
		bnz		fl
		call	TXcrlf
	return
; -----------------------------------------


; -----------------------------------------
; Prints Board's upper border.
; -----------------------------------------
print_upper_border
	movlw	cols_number
	movwf	COUNTER_COLS
	movlw	.0
	movwf	TMP
	movlw	' '
	call	TXbyte
	call	TXbyte
	call	TXbyte
	movlw	.201			; left upper corner
	call	TXbyte
	pub:
		movlw	cell_width
		movwf	COUNTER		; COUNTER <-- cell_width
		pub_loop:
			movlw	.205		; horizontal kav
			call	TXbyte
			decfsz	COUNTER
			bra		pub_loop
		movlw	.203		; kav with chupchik down
		call	TXbyte
		decf	COUNTER_COLS
		bnz		pub
		print	reverse_one
		movlw	.187		; right upper corner
		call	TXbyte
		call	TXcrlf
	return
; -----------------------------------------



; -----------------------------------------
; Prints Board's lower border.
; -----------------------------------------
print_lower_border
	movlw	cols_number
	movwf	COUNTER_COLS
	movlw	.0
	movwf	TMP
	movlw	' '
	call	TXbyte
	call	TXbyte
	call	TXbyte
	movlw	.200			; right bottom corner
	call	TXbyte
	plb:
		movlw	cell_width
		movwf	COUNTER		; COUNTER <-- cell_width
		plb_loop:
			movlw	.205		; kav
			call	TXbyte
			decfsz	COUNTER
			bra		plb_loop
		movlw	.202		; kav with chupchik up
		call	TXbyte
		decf	COUNTER_COLS
		bnz		plb
		print	reverse_one
		movlw	.188		; left bottom corner
		call	TXbyte
		call	TXcrlf
	return
; -----------------------------------------



; -----------------------------------------
; Prints Board's horizontal border (border between each two lines).
; -----------------------------------------
print_horizontal_border
	movlw	cols_number
	movwf	COUNTER_COLS
	movlw	.0
	movwf	TMP
	movlw	' '
	call	TXbyte
	call	TXbyte
	call	TXbyte
	movlw	.204			; kav with chupchik to the right
	call	TXbyte
	phb:
		movlw	cell_width
		movwf	COUNTER		; COUNTER <-- cell_width
		phb_loop:
			movlw	.205		; kav
			call	TXbyte
			decfsz	COUNTER
			bra		phb_loop
		movlw	.206		; cross (+)
		call	TXbyte
		decf	COUNTER_COLS
		bnz		phb
		print	reverse_one
		movlw	.185		; kav with chupchik to the left
		call	TXbyte
		call	TXcrlf
	return
; -----------------------------------------



; -----------------------------------------
; Prints cell seperator (between each two cells).
; -----------------------------------------
print_cells_seperator
	movlw	.186		; draw kav
	call 	TXbyte
	return
; -----------------------------------------




;Delay of 1 second - Subroutine
;******************************
;  Calculation of the Delay time -
;  "movlw" , "movwf" , "decf" , "nop" - 1 cycle.
;  "bnz" - 2 cycles (if skipping, almost always)
;  Each cycle takes 0.000001 (1e-6) second in the PIC (4MHz) => 200e-3 second in the 
;           simulator (20MHz).
;  Therfore we have 1 million cycles to count.
;  We need 3 registers in order to calculate (by product)  (binary) 1 million 
;           (11110100001001000000) with good approximation 
;  With n1=255, n2=30, n3=42 the delay time (in the PIC) is 1.003177 second which is
;            approximetly 1 second

;Constants
n1  equ .255
n2  equ .30
n3  equ .42

;Variables
DELAY_DATA     UDATA
t1  res 1
t2  res 1
t3  res 1

DELAY          CODE
Delay
  movlw n1
  movwf t1

ONE  ; Loop 1 (outer loop)
        movlw n2
        movwf t2  

TWO     ; Loop 2 (in)
              movlw n3
              movwf t3
              nop

THREE       ; Loop 3 (in-in)
                    decf t3
                    bnz THREE

              decf t2
              bnz TWO

       decf t1
       bnz ONE

  return 1

end_code
	print	good_bye_message
	bra		$
	end

